//
// Created by HP on 2025/11/17.
//

#include "Ask.h"
#include <iostream>

const std::string AskRequestType::buyTicket = "buyTicket";
const std::string AskRequestType::refundTicket = "refundTicket";

const std::string AskStatus::pending = "pending";
const std::string AskStatus::approved = "approved";
const std::string AskStatus::rejected = "rejected";
const std::string AskStatus::cancelled = "cancelled";

Ask::Ask() : Model("asks") {
    this->requestType = AskRequestType::buyTicket;
    this->status = AskStatus::pending;
    setTableDefault("userId", "INT NOT NULL");
    setTableDefault("ticketId", "INT NOT NULL");
    setTableDefault("requestType", "VARCHAR(50) NOT NULL");
    setTableDefault("status", "VARCHAR(50) NOT NULL DEFAULT '" + AskStatus::pending + "'");
    setTableDefault("quantity", "INT NOT NULL DEFAULT 1");
    setTableDefault("price", "VARCHAR(50) NOT NULL");
    setTableDefault("reason", "TEXT");
    setTableDefault("createdAt", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
    setTableDefault("updatedAt", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
}

void Ask::bind(const std::string& key, const std::string& value) {
    if (!TableCols.count(key)) {
        std::cerr << "Error: Invalid key for ask bind" << std::endl;
        return;
    }
    if (TableCols[key].find("UNIQUE") == std::string::npos && key != "id") {
        std::cerr << "Error: Key is not unique for ask bind" << std::endl;
        return;
    }

    std::string selectSql = "SELECT * FROM " + TableName + " WHERE " + key + " = '" + Model::escapeSqlLiteral(value) + "';";
    std::vector<std::map<std::string, std::string>> result = DBConnector::getInstance()->query(selectSql);

    if (result.empty()) {
        std::cerr << "bind failed: SQL execution error or no result. SQL: " << selectSql << std::endl;
        return;
    }

    std::cout << "bind success. Table: " << TableName << std::endl;

    if (result.size() > 1) {
        std::cerr << "Error: Multiple asks found with the same " << key << std::endl;
        return;
    } else if (result.size() == 1) {
        this->id = result[0]["id"];
        this->userId = result[0]["userId"];
        this->ticketId = result[0]["ticketId"];
        this->requestType = result[0]["requestType"];
        this->status = result[0]["status"];
        this->quantity = result[0]["quantity"];
        this->price = result[0]["price"];
        this->reason = result[0].count("reason") > 0 ? result[0]["reason"] : "";
        this->createdAt = result[0]["createdAt"];
        this->updatedAt = result[0]["updatedAt"];
    }
}

bool Ask::save() {
    std::string createAskSql = "INSERT INTO " + TableName + " (userId, ticketId, requestType, status, quantity, price";
    std::string valuesSql = " VALUES (" + userId + ", " + ticketId + ", '" 
                           + Model::escapeSqlLiteral(requestType) + "', '" 
                           + Model::escapeSqlLiteral(status) + "', " 
                           + quantity + ", '" 
                           + Model::escapeSqlLiteral(price) + "'";
    
    if (!reason.empty()) {
        createAskSql += ", reason";
        valuesSql += ", '" + Model::escapeSqlLiteral(reason) + "'";
    }
    
    createAskSql += ")";
    valuesSql += ");";
    
    std::string fullSql = createAskSql + valuesSql;
    int executeCode = DBConnector::getInstance()->execute(fullSql);
    if (executeCode == -1) {
        std::cerr << "create ask failed: SQL execution error. SQL: " << fullSql << std::endl;
        return false;
    } else {
        std::cout << "create ask success. Table: " << TableName << std::endl;
        return true;
    }
}
